//
// Created by 吴喆 on 2020/3/1.
//

#include "Manager.h"
#include "game/Game.h"
#include <glad/glad.h>
#include "../util/GameUtil.h"

//const std::mutex Manager::lock = std::mutex();
Manager *Manager::manager = new Manager();/*NOLINT*/
Manager *Manager::getInstance() {
    return manager;
}

void onResizeWrapper(GLFWwindow *win, int width, int height) {
    Manager::getInstance()->onResize(win, width, height);
}

void Manager::onResize(GLFWwindow *win, int width, int height) {
    gui->zoomCallback(width, height);
}

void Manager::init() {

    state = programState::Starting;
    GLboolean status;
    // 初始化配置工具
    status = ConfigUtil::init();
    if (GL_FALSE == status) {
        Console::ERR("init config failed");
        throw std::exception();
    }

    // init
    status = glfwInit();
    if (GL_FALSE == status) {
        Console::ERR("init GLFW failed");
        throw std::exception();
    }

    //Try to use OPENGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    win = glfwCreateWindow(ConfigUtil::getPropI(ConfigConst::SCREEN_WIDTH),
                           ConfigUtil::getPropI(ConfigConst::SCREEN_HEIGHT),
                           ConfigUtil::getProp(ConfigConst::GAME_TITLE).c_str(), nullptr, nullptr);
    glfwSetWindowAspectRatio(win, ConfigUtil::getPropI(ConfigConst::SCREEN_WIDTH),
                             ConfigUtil::getPropI(ConfigConst::SCREEN_HEIGHT));
    glfwSetWindowSizeCallback(win, &onResizeWrapper);

    if (!win) {
        Console::ERR("create window failed");
        throw std::exception();
    }

    // 帧交换速率
    glfwSwapInterval(ConfigUtil::getPropI(ConfigConst::VERTICAL_SYN));

    glfwMakeContextCurrent(win);
    if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
        Console::ERR("init GLAD failed");
        throw std::exception();
    }
    // 初始化鼠键回调
    Input::getInstance()->initCallback(win,
                                       std::pair<int, int>(ConfigUtil::getPropI(ConfigConst::SCREEN_WIDTH) / 2,
                                                           ConfigUtil::getPropI(ConfigConst::SCREEN_HEIGHT) / 2));

    cTime = CTime::getInstance();


    // 初试化game
    game = DemoGame::getInstance();
    game->init();
    // 初始化imgui
    gui = Gui::getInstance();
    gui->init(win, ConfigUtil::getPropI(ConfigConst::SCREEN_WIDTH),
              ConfigUtil::getPropI(ConfigConst::SCREEN_HEIGHT));

    glEnable(GL_CULL_FACE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    state = programState::Running;

}

// 输入逻辑
void Manager::input() {

}

void Manager::early() {
    //Timer timers need to be updated
    glfwPollEvents();
    cTime->update();
}

// 游戏逻辑
void Manager::logic() {
    game->update();
}

void Manager::render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);/*NOLINT*/
    glClearColor(27.0f / 255, 38.0f / 255, 49.0f / 255, 1.0f);
    game->render();
    gui->render();
}

void Manager::late() {
    glfwSwapBuffers(win);
    if (glfwWindowShouldClose(win)) {
        Manager::quit();
    }
}

void Manager::quit() {
    state = programState::Closing;
    //Destroy class objects
    glfwDestroyWindow(win);
    //Close window
    glfwTerminate();
}

